//
// @Author: xzw
// @Description:
// @Version: 1.0.0
// @Date: 2021/3/11 下午7:52
// @Copyright: MIN-Group；国家重大科技基础设施——未来网络北大实验室；深圳市信息论与未来网络重点实验室
//


const identity = require("../../../identity")
const sqlite = require("../sqlite")
const uti = require("../../../../crypto/utils")
const com = require("../../../../common")
const cer = require("../../../../crypto/cert/cert")
const inter = require("./internal")

// 
// 插入identity
//
// @param identity *identity.Identity
// @returns (bool, error)
// 
function PersistIdentity(identity) {
    let id = GetIdentityByNameFromStorage(identity.Name)
    if (id[0] != null) {
        return [false, new Error("The name has existed!!!")]
    }

    let conn = sqlite.GetConn()
    if (conn[1] != null) {
        return [false, conn[1]]
    }
    var pubStr = ""
    var priStr = ""
    var algo = 0
    var certStr = ""
    var prikeyRawByte = ""
    if (identity.Prikey != null) {
        var res1 = uti.MarshalPrivateKey(identity.Prikey)
        priStr = new Buffer.from(uti.Bytes2Str(res1[1]),'hex').toString('base64')
        // priStr = base64.StdEncoding.EncodeToString(priByte)
        algo = res1[0]
    }
    if (identity.Pubkey != null) {
        var res2 = uti.MarshalPublicKey(identity.Pubkey)
        pubStr = new Buffer.from(uti.Bytes2Str(res2[1]),'hex').toString('base64')
        // pubStr = base64.StdEncoding.EncodeToString(pubByte)
        algo = res2[0]
    }
    algo = identity.KeyParam.PublicKeyAlgorithm
    var sign = identity.KeyParam.SignatureAlgorithm

    if (identity.Cert === undefined || identity.Cert === null) {
        certStr = ""
    } else {
        var certres = identity.Cert.ToPem(null, com.SymmetricAlgorithm.SM4ECB)
        if (certres[1] != null) {
            return [false, certres[1]]
        }else{
            certStr = certres[0]
        }
    }

    if (identity.PrikeyRawByte != null){
        prikeyRawByte = new Buffer.from(uti.Bytes2Str(identity.PrikeyRawByte)).toString('base64')
        // prikeyRawByte= base64.StdEncoding.EncodeToString(identity.PrikeyRawByte)
    }

    try{
        console.log("即将插入的identity：",identity.Name, "pubStr", pubStr, "priStr", priStr, "algo", algo, "sign", sign,"password", identity.Passwd, "certStr", certStr, "prikeyRawByte", prikeyRawByte)
        var stmt = conn[0].prepare("INSERT INTO identityinfo(name, pubkey, prikey, pubkey_algo, signature_algo, pass, " +"cert,prikey_raw_byte) values(?,?,?,?,?,?,?,?)")
    
        var info = stmt.run(identity.Name, pubStr, priStr, algo, sign,identity.Passwd, certStr, prikeyRawByte)
        console.log("insert info :", info)
    }catch(err){
        return [false, err]
    }

    conn[0].close()

    return [true, null]
}

// 
// 根据名字查询identity
//
// @param name string
// @returns (*identity.Identity, error)
// 
function GetIdentityByNameFromStorage(name) {
    let db = sqlite.GetConn()
    if (db[1] != null) {
        return [null, db[1]]
    }

    db[0].close
    return inter.getIdentityByNameFromStorage(name, db[0])
}

// 
// 查询所有identity
//
// @param 
// @returns ([]*identity.Identity, error)
// 
function GetAllIdentityFromStorage() {
    var db = sqlite.GetConn()
    // defer db.Close()
    if (db[1] != null) {
        return [null, db[1]]
    }
    var stmt
    var rows 
    try{
        stmt = db[0].prepare('select * from identityinfo');
        rows = stmt.all();
        console.log("rows", rows)
    }catch(err){
        return [null, err]
    }
    var res = []
    var id 
	for (var i = 0; i<rows.length; i++) {
		id = inter.getIdentityFromSqlRows(rows[i])
		if (id[1] != null) {
		    console.log("get错误", id[1])
			return [null, id[1]]
		}
        console.log("id from db is", id[0])
		res = res.concat(id[0])
	}

    db[0].close
    // var p = new Promise(function(resolve, reject){
    //     db[0].all("select * from identityinfo", function(err, rows){
    //     if(err){
    //         console.log("select from identityinfo error,",err.message);
    //         reject(err.message)
    //     }else{
    //         console.log("select identity success");
    //         resolve(rows)
    //     }
    // })
    // })
    return [res, null]                                              
}

// 
// 设置默认的identity
// @param name string
// @returns (bool, error)
// 
function SetDefaultIdentityByNameInStorage(name) {
    for (var i = 0 ; i <4 ; i++) {
        var res = setDefaultIdentityByNameInStorage(name)
        if (i === 3){
            return res
        }

        if (res[0] === true) {
            return res
        }else{
            if (res[1] == "database is locked") {
                sleep(50)
            }else{
                return res
            }
        }
    }
    return [false, null]
}

// 
// 设置默认的identity
// @param name string
// @returns (bool, error)
// 
function setDefaultIdentityByNameInStorage(name) {
    var db = sqlite.GetConn()
    // defer db.Close()
    if (db[1] != null) {
        return [false, db[1]]
    }
    var stmt
    var row
    try{
        stmt = db[0].prepare("select * from identityinfo where name = ?");
        // var rows = stmt.all();
        // var setdefault = db[0].transaction((name)=>{stmt.get(name)})
        row = stmt.get(name)
        // tx, err := db.Begin()
        // row := tx.QueryRow("select * from identityinfo where name = ?", name)
    }catch(err){
        return [false, err]
    }


    var id = inter.getDefaultIdentityFromStorage(row)
    if (id[1] != null) {
        return [false, id[1]]
    }
    if (id[0] === null) {
        return [false, null]
    }

    var stmt1 = db[0].prepare("SELECT * from identityinfo where is_default = 1")
    var row1 = stmt1.get()
    if (row1 != null || row1 != undefined){
        var id1 = inter.getDefaultIdentityFromStorage(row1)
        if (id1[1] != null) {
            // tx.Rollback()
            return [false, null]
        }
        if (id1[0] != null) {
            var flag = inter.cancelDefaultIdentityFromStorage(id1.Name, db[0])
            if (flag[0] === false) {
                return [false, flag[1]]
            }
        }
    }
    var flag1 = inter.setDefaultIdentityFromStorage(name, db[0])
    if (flag1[0] == false) {
        // tx.Rollback()
        return [false, flag1[1]]
    }
    

    db[0].close
    // tx.Commit()
    return [true, null]

}

// 
// 获取默认identity
// @param 
// @returns (*identity.Identity, error)
// 
function GetDefaultIdentityFromStorage()  {
    var db = sqlite.GetConn()
    // defer db.Close()
    if (db[1] != null) {
        return [null, db[1]]
    }

    var stmt = db[0].prepare("SELECT * from identityinfo where is_default = 1")
    var row = stmt.get()
    db[0].close
    return inter.getDefaultIdentityFromStorage(row)
}

// 
// 删除identity
// @param name string
// @returns (bool, error)
// 
function  DeleteIdentityByName(name) {
    var db = sqlite.GetConn()
    // defer db.Close()
    if (db[1] != null) {
        return [false, db[1]]
    }

    var stmt
    var info
    try{
        stmt = db[0].prepare("delete from identityinfo where name = ?")
        info = stmt.run(name);
    }catch(err){
        return [false, err]
    }

    console.log("delete info: ", info)
    // , [name],  function (err) {
    //     if (err) {
    //         return console.log(err.message)
    //     }
    //     console.log('deleted identityinfo: ', this)}
    // if err != nil {
    //     return false, err
    // }
    // defer stmt.Close()
    // _, err = stmt.Exec(name)
    // if err != nil {
    //     return false, err
    // }
    db[0].close
    return [true, null]
}

// 函数实现，参数 delay 单位 毫秒 ；
function sleep(delay) {
    var start = (new Date()).getTime();
    while ((new Date()).getTime() - start < delay) {
        // 使用  continue 实现；
        continue; 
    }
}

module.exports = {
    PersistIdentity: PersistIdentity,
    GetIdentityByNameFromStorage: GetIdentityByNameFromStorage,
    GetAllIdentityFromStorage: GetAllIdentityFromStorage,
    DeleteIdentityByName: DeleteIdentityByName,
    SetDefaultIdentityByNameInStorage: SetDefaultIdentityByNameInStorage,
    GetDefaultIdentityFromStorage: GetDefaultIdentityFromStorage
}